﻿using MediatR;
using Microsoft.AspNetCore.Mvc;
using Sgr.Application.Queries;
using Sgr.AspNetCore.ActionFilters.AuditLogs;
using Sgr.AspNetCore.ActionFilters.Permissions;
using Sgr.Domain.Entities;
using Sgr.UPMS.Application.Commands.UserProfile;
using Sgr.UPMS.Application.Queries;
using Sgr.UPMS.Application.Services;
using Sgr.UPMS.Application.ViewModels;

namespace Sgr.UPMS.Controllers
{
    /// <summary>
    /// 用户个人信息接口
    /// </summary>
    [Route("api/v1/sgr/user-profile")]
    [ApiController]
    [Produces("application/json")]
    [Tags("UserProfile")]
    public class UserProfileController : ControllerBase
    {
        private readonly IMediator _mediator;

        public UserProfileController(IMediator mediator)
        {
            _mediator = mediator ?? throw new ArgumentNullException(nameof(mediator));
        }

        #region 用户个人资料管理

        /// <summary>
        /// 获取当前用户的个人信息
        /// </summary>
        [CheckPermission]
        [HttpGet("current-profile")]
        [ProducesResponseType(typeof(OutPersonalViewModel), StatusCodes.Status200OK)]
        [ProducesResponseType(StatusCodes.Status404NotFound)]
        [AuditLogActionFilter("获取当前用户的个人信息")]
        public async Task<ActionResult<OutPersonalViewModel>> GetCurrentProfileAsync(
            [FromServices] IUserQueries userQueries,
            CancellationToken cancellationToken = default)
        {
            var profile = await userQueries.GetCurrentUserProfileAsync(cancellationToken);
            return profile != null ? Ok(profile) : NotFound();
        }

        /// <summary>
        /// 更新用户个人信息
        /// </summary>
        /// <param name="command">命令</param>
        /// <param name="cancellationToken">取消令牌</param>
        [CheckPermission(Permissions.ModifyUser)]
        [HttpPost("profile")]
        [ProducesResponseType(typeof(bool), StatusCodes.Status200OK)]
        [AuditLogActionFilter("更新用户个人信息")]
        public async Task<ActionResult<bool>> UpdateProfileAsync([FromBody] ModifyUserCommand command, CancellationToken cancellationToken)
        {
            var result = await _mediator.Send(command, cancellationToken);
            return !result.IsSuccess ? this.CustomBadRequest(result.Message) : Ok(result.Data);
        }

        #endregion 用户个人资料管理

        #region 密码管理

        /// <summary>
        /// 忘记密码（发送重置密码邮件/短信）
        /// </summary>
        /// <param name="command">命令</param>
        /// <param name="cancellationToken">取消令牌</param>
        [HttpPost("password/forgot")]
        [ProducesResponseType(typeof(bool), StatusCodes.Status200OK)]
        [AuditLogActionFilter("忘记密码请求", false)]
        public async Task<ActionResult<bool>> ForgotPasswordAsync([FromBody] ForgotPasswordCommand command, CancellationToken cancellationToken)
        {
            var result = await _mediator.Send(command, cancellationToken);
            return !result.IsSuccess ? this.CustomBadRequest(result.Message ?? "重置密码请求失败") : Ok(result.Data);
        }

        /// <summary>
        /// 修改用户密码
        /// </summary>
        /// <param name="command">命令</param>
        /// <param name="cancellationToken">取消令牌</param>
        [CheckPermission(Permissions.ModifyPassword)]
        [HttpPost("password/change")]
        [ProducesResponseType(typeof(bool), StatusCodes.Status200OK)]
        [AuditLogActionFilter("修改用户密码", false)]
        public async Task<ActionResult<bool>> ChangePasswordAsync([FromBody] ModifyPasswordCommand command, CancellationToken cancellationToken)
        {
            var result = await _mediator.Send(command, cancellationToken);
            return !result.IsSuccess ? this.CustomBadRequest(result.Message) : Ok(result.Data);
        }

        #endregion 密码管理

        #region 身份验证绑定

        /// <summary>
        /// 绑定邮箱地址
        /// </summary>
        /// <param name="command">命令</param>
        /// <param name="cancellationToken">取消令牌</param>
        [CheckPermission(Permissions.ModifyUser)]
        [HttpPost("bind-email")]
        [ProducesResponseType(typeof(bool), StatusCodes.Status200OK)]
        [AuditLogActionFilter("绑定邮箱地址")]
        public async Task<ActionResult<bool>> BindEmailAsync([FromBody] BindEmailCommand command, CancellationToken cancellationToken)
        {
            var result = await _mediator.Send(command, cancellationToken);
            return !result.IsSuccess ? this.CustomBadRequest(result.Message) : Ok(result.Data);
        }

        /// <summary>
        /// 绑定手机号码
        /// </summary>
        /// <param name="command">命令</param>
        /// <param name="cancellationToken">取消令牌</param>
        [CheckPermission(Permissions.ModifyUser)]
        [HttpPost("bind-phone")]
        [ProducesResponseType(typeof(bool), StatusCodes.Status200OK)]
        [AuditLogActionFilter("绑定手机号码")]
        public async Task<ActionResult<bool>> BindPhoneAsync([FromBody] BindPhoneCommand command, CancellationToken cancellationToken)
        {
            var result = await _mediator.Send(command, cancellationToken);
            return !result.IsSuccess ? this.CustomBadRequest(result.Message) : Ok(result.Data);
        }

        #endregion 身份验证绑定

        #region 组织结构相关

        /// <summary>
        /// 获取指定组织的部门信息
        /// </summary>
        [CheckPermission(Permissions.ViewDepartment)]
        [HttpGet("departments/by-org/{orgId:long}")]
        [ProducesResponseType(typeof(IEnumerable<NameValue>), StatusCodes.Status200OK)]
        [ProducesResponseType(StatusCodes.Status404NotFound)]
        [AuditLogActionFilter("获取指定组织的部门信息")]
        public async Task<ActionResult<IEnumerable<NameValue>>> GetDepartmentsByOrgIdAsync(
            long orgId,
            [FromServices] IOrgBasicDataCacheService cacheService,
            CancellationToken cancellationToken = default)
        {
            if (orgId <= 0) return NotFound();

            var departments = await cacheService.GetDepartmentNamesAsync(orgId, cancellationToken);
            if (departments?.Count > 0)
            {
                var validDepartments = departments
                    .Where(d => d.Value.States == EntityStates.Normal)
                    .Select(d => new NameValue(d.Value.Name, d.Value.Value) { ParentValue = d.Value.ParentValue });

                return validDepartments.Any() ? Ok(validDepartments) : NotFound();
            }
            return NotFound();
        }

        /// <summary>
        /// 获取当前用户所在组织的部门信息
        /// </summary>
        [CheckPermission]
        [HttpGet("departments")]
        [ProducesResponseType(typeof(IEnumerable<NameValue>), StatusCodes.Status200OK)]
        [ProducesResponseType(StatusCodes.Status404NotFound)]
        [AuditLogActionFilter("获取当前用户所在组织的部门信息")]
        public async Task<ActionResult<IEnumerable<NameValue>>> GetDepartmentsAsync(
            [FromServices] IOrgBasicDataCacheService cacheService,
            [FromServices] ICurrentUser currentUser,
            CancellationToken cancellationToken = default)
        {
            long orgId = QueryHelper.GetOrgId(currentUser);
            return await GetDepartmentsByOrgIdAsync(orgId, cacheService, cancellationToken);
        }

        /// <summary>
        /// 获取指定组织的岗位信息
        /// </summary>
        [CheckPermission(Permissions.ViewDuty)]
        [HttpGet("duties/by-org/{orgId:long}")]
        [ProducesResponseType(typeof(IEnumerable<NameValue>), StatusCodes.Status200OK)]
        [ProducesResponseType(StatusCodes.Status404NotFound)]
        [AuditLogActionFilter("获取指定组织的岗位信息")]
        public async Task<ActionResult<IEnumerable<NameValue>>> GetDutiesByOrgIdAsync(
            long orgId,
            [FromServices] IOrgBasicDataCacheService cacheService,
            CancellationToken cancellationToken = default)
        {
            if (orgId <= 0) return NotFound();

            var duties = await cacheService.GetDutyNamesAsync(orgId, cancellationToken);
            if (duties?.Count > 0)
            {
                var validDuties = duties
                    .Where(d => d.Value.States == EntityStates.Normal)
                    .Select(d => new NameValue(d.Value.Name, d.Value.Value));

                return validDuties.Any() ? Ok(validDuties) : NotFound();
            }
            return NotFound();
        }

        /// <summary>
        /// 获取当前用户所在组织的岗位信息
        /// </summary>
        [CheckPermission]
        [HttpGet("duties")]
        [ProducesResponseType(typeof(IEnumerable<NameValue>), StatusCodes.Status200OK)]
        [ProducesResponseType(StatusCodes.Status404NotFound)]
        [AuditLogActionFilter("获取当前用户所在组织的岗位信息")]
        public async Task<ActionResult<IEnumerable<NameValue>>> GetDutiesAsync(
            [FromServices] IOrgBasicDataCacheService cacheService,
            [FromServices] ICurrentUser currentUser,
            CancellationToken cancellationToken = default)
        {
            long orgId = QueryHelper.GetOrgId(currentUser);
            return await GetDutiesByOrgIdAsync(orgId, cacheService, cancellationToken);
        }

        /// <summary>
        /// 获取指定组织信息
        /// </summary>
        [CheckPermission(Permissions.ViewOrg)]
        [HttpGet("organization/by-org/{orgId:long}")]
        [ProducesResponseType(typeof(NameValue), StatusCodes.Status200OK)]
        [ProducesResponseType(StatusCodes.Status404NotFound)]
        [AuditLogActionFilter("获取指定组织信息")]
        public async Task<ActionResult<NameValue>> GetOrganizationByOrgIdAsync(
            long orgId,
            [FromServices] IOrgBasicDataCacheService cacheService,
            CancellationToken cancellationToken = default)
        {
            if (orgId <= 0) return NotFound();

            var org = await cacheService.GetOrgNameAsync(orgId, cancellationToken);
            return org != null ? Ok(new NameValue(org.Name, org.Value)) : NotFound();
        }

        /// <summary>
        /// 获取当前用户所在组织信息
        /// </summary>
        [CheckPermission]
        [HttpGet("organization")]
        [ProducesResponseType(typeof(NameValue), StatusCodes.Status200OK)]
        [ProducesResponseType(StatusCodes.Status404NotFound)]
        [AuditLogActionFilter("获取当前用户所在组织信息")]
        public async Task<ActionResult<NameValue>> GetOrganizationAsync(
            [FromServices] IOrgBasicDataCacheService cacheService,
            [FromServices] ICurrentUser currentUser,
            CancellationToken cancellationToken = default)
        {
            long orgId = QueryHelper.GetOrgId(currentUser);
            return await GetOrganizationByOrgIdAsync(orgId, cacheService, cancellationToken);
        }

        #endregion 组织结构相关
    }
}